package com.salmon.common.xml.utils;

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;

public class XmlUtils {

    /**
     * 将xml转化成对象
     * @param xmlStr xml 字符串
     * @param beanType 要转换的class类
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T toObject(String xmlStr, Class<T> beanType) {
        try {
            JAXBContext context = JAXBContext.newInstance(beanType);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            return (T)unmarshaller.unmarshal(new StringReader(xmlStr));
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成不包含报文头的xml文件
     * @param obj
     * @return
     */
    public static String convertToXml(Object obj) {
        return convertToXml(obj, false);
    }

    /**
     * 生成是否包含报文头的xml文件xmlHeader 为true 生成带报文头的xml文件
     * @param obj 要转换的对象
     * @param xmlHeader 添加xml报文头
     *        <?xml version="1.0" encoding="utf-8"?>
     * @return
     */
    public static String convertToXml(Object obj, boolean xmlHeader) {
        return convertToXml(obj,true, xmlHeader);
    }

    /**
     * 转换对象到xml文件
     * @param obj 要转换的对象
     * @param formatted 是否格式化输出
     * @param xmlHeader 添加xml报文头
     * @return
     */
    public static String convertToXml(Object obj, boolean formatted, boolean xmlHeader) {
        return convertToXml(obj, StandardCharsets.UTF_8.name(), formatted,xmlHeader);
    }

    public static String convertToXml(Object obj, String encoding, boolean formatted, boolean xmlHeader) {
        String result = null;
        try {
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formatted);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
            //生成xml的默认报文头。
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, xmlHeader);
            //转换所有的适配字符，包括xml实体字符&lt;和&gt;
            marshaller.setProperty("com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler",
                    new CharacterEscapeHandler() {
                        @Override
                        public void escape(char[] ch, int start, int length, boolean isAttVal,
                                           Writer writer) throws IOException {
                            writer.write(ch, start, length);
                        }
                    });

            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            result = writer.toString();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return result;
    }

}
